import os
import uuid
import logging
from io import BytesIO
from django.db import models
from django.conf import settings
from django.utils import timezone
from django.contrib.auth.models import AbstractUser
from django.core.files.base import ContentFile
from django.db.models.signals import post_save
from django.dispatch import receiver
from utils.image_utils import ImageProcessor

logger = logging.getLogger('api')

class User(AbstractUser):
    """
    用户模型，继承自Django的AbstractUser
    添加了微信相关的用户信息字段
    """
    openid = models.CharField(max_length=100, blank=True, null=True, unique=True, verbose_name='微信OpenID')
    avatar = models.CharField(max_length=500, blank=True, null=True, verbose_name='头像')
    phone = models.CharField(max_length=20, null=True, blank=True, verbose_name="手机号")
    role = models.CharField(max_length=20, default='customer', choices=[
        ('customer', '顾客'),
        ('admin', '管理员'),
        ('staff', '员工')
    ], verbose_name='角色')
    device_id = models.CharField(max_length=100, blank=True, null=True, verbose_name='设备ID')
    
    class Meta:
        verbose_name = "用户"
        verbose_name_plural = verbose_name
    
    def __str__(self):
        return self.username or self.openid


class FoodCategory(models.Model):
    """
    食品分类模型
    """
    name = models.CharField(max_length=100, verbose_name="分类名称")
    icon = models.ImageField(upload_to='categories/', null=True, blank=True, verbose_name="分类图标")
    icon_url = models.URLField(max_length=500, null=True, blank=True, verbose_name="分类图标URL")
    sort_order = models.IntegerField(default=0, verbose_name="排序")
    is_active = models.BooleanField(default=True, verbose_name="是否有效")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    
    class Meta:
        verbose_name = "食品分类"
        verbose_name_plural = verbose_name
        ordering = ['sort_order', 'id']
    
    def __str__(self):
        return self.name
    
    @property
    def get_icon(self):
        """优先返回上传的图片，如果没有则返回URL"""
        if self.icon:
            return self.icon.url
        return self.icon_url
    
    def save(self, *args, **kwargs):
        """重写保存方法，处理图像压缩和转换"""
        # 检查是否有图像文件需要处理
        if self.icon and hasattr(self.icon, 'file'):
            try:
                # 获取分类图标的处理配置
                img_config = settings.IMAGE_PROCESSING.get('CATEGORY', settings.IMAGE_PROCESSING['DEFAULT'])
                
                # 获取原始文件名和扩展名
                original_name = self.icon.name
                # 生成新的文件名
                new_name = f"{original_name.split('.')[0]}.webp"
                
                # 压缩图像
                logger.info(f"正在处理分类图标: {original_name}")
                compressed_image = ImageProcessor.process_uploaded_file(
                    self.icon,
                    target_format=img_config['FORMAT'],
                    target_size_kb=img_config['TARGET_SIZE_KB'],
                    max_size=img_config['MAX_SIZE'],
                    quality=img_config['QUALITY']
                )
                
                # 设置压缩后的图像
                self.icon.save(
                    new_name,
                    ContentFile(compressed_image.getvalue()),
                    save=False  # 避免递归保存
                )
                logger.info(f"分类图标已处理: {new_name}")
            except Exception as e:
                logger.error(f"处理分类图标时出错: {str(e)}")
        
        # 调用父类的save方法
        super().save(*args, **kwargs)


class Food(models.Model):
    """
    食品模型
    """
    category = models.ForeignKey(FoodCategory, on_delete=models.CASCADE, related_name='foods', verbose_name="所属分类")
    name = models.CharField(max_length=100, verbose_name="食品名称")
    description = models.TextField(null=True, blank=True, verbose_name="描述")
    price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="价格")
    original_price = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True, verbose_name="原价")
    image = models.ImageField(upload_to='foods/', null=True, blank=True, verbose_name="主图")
    image_url = models.URLField(max_length=500, null=True, blank=True, verbose_name="主图URL")
    sold = models.IntegerField(default=0, verbose_name="已售数量")
    rating = models.DecimalField(max_digits=3, decimal_places=1, default=5.0, verbose_name="评分")
    is_hot = models.BooleanField(default=False, verbose_name="是否热销")
    is_new = models.BooleanField(default=False, verbose_name="是否新品")
    is_active = models.BooleanField(default=True, verbose_name="是否上架")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    
    class Meta:
        verbose_name = "食品"
        verbose_name_plural = verbose_name
        ordering = ['-is_hot', '-is_new', '-sold']
    
    def __str__(self):
        return self.name
    
    @property
    def get_image(self):
        """优先返回上传的图片，如果没有则返回URL"""
        if self.image:
            return self.image.url
        return self.image_url
    
    def save(self, *args, **kwargs):
        """重写保存方法，处理图像压缩和转换"""
        # 检查是否有图像文件需要处理
        if self.image and hasattr(self.image, 'file'):
            try:
                # 获取食品图片的处理配置
                img_config = settings.IMAGE_PROCESSING.get('FOOD', settings.IMAGE_PROCESSING['DEFAULT'])
                
                # 获取原始文件名和扩展名
                original_name = self.image.name
                # 生成新的文件名
                new_name = f"{original_name.split('.')[0]}.webp"
                
                # 压缩图像
                logger.info(f"正在处理食品图片: {original_name}")
                compressed_image = ImageProcessor.process_uploaded_file(
                    self.image,
                    target_format=img_config['FORMAT'],
                    target_size_kb=img_config['TARGET_SIZE_KB'],
                    max_size=img_config['MAX_SIZE'],
                    quality=img_config['QUALITY']
                )
                
                # 设置压缩后的图像
                self.image.save(
                    new_name,
                    ContentFile(compressed_image.getvalue()),
                    save=False  # 避免递归保存
                )
                logger.info(f"食品图片已处理: {new_name}")
            except Exception as e:
                logger.error(f"处理食品图片时出错: {str(e)}")
        
        # 调用父类的save方法
        super().save(*args, **kwargs)


class FoodImage(models.Model):
    """
    食品图片模型
    """
    food = models.ForeignKey(Food, on_delete=models.CASCADE, related_name='images', verbose_name="所属食品")
    image_url = models.URLField(max_length=500, verbose_name="图片URL")
    sort_order = models.IntegerField(default=0, verbose_name="排序")
    
    class Meta:
        verbose_name = "食品图片"
        verbose_name_plural = verbose_name
        ordering = ['sort_order']
    
    def __str__(self):
        return f"{self.food.name}的图片{self.id}"


class FoodSpec(models.Model):
    """
    食品规格模型
    """
    food = models.ForeignKey(Food, on_delete=models.CASCADE, related_name='specs', verbose_name="所属食品")
    name = models.CharField(max_length=100, verbose_name="规格名称")
    extra_price = models.DecimalField(max_digits=10, decimal_places=2, default=0, verbose_name="额外价格")
    is_default = models.BooleanField(default=False, verbose_name="是否默认规格")
    
    class Meta:
        verbose_name = "食品规格"
        verbose_name_plural = verbose_name
    
    def __str__(self):
        return f"{self.food.name}-{self.name}"


class CartItem(models.Model):
    """
    购物车项模型
    """
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='cart_items', verbose_name="用户")
    food = models.ForeignKey(Food, on_delete=models.CASCADE, verbose_name="食品")
    spec = models.ForeignKey(FoodSpec, on_delete=models.CASCADE, null=True, blank=True, verbose_name="规格")
    count = models.IntegerField(default=1, verbose_name="数量")
    is_checked = models.BooleanField(default=True, verbose_name="是否选中")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    
    class Meta:
        verbose_name = "购物车项"
        verbose_name_plural = verbose_name
        unique_together = ['user', 'food', 'spec']
    
    def __str__(self):
        return f"{self.user.username}的购物车-{self.food.name}"
    
    @property
    def price(self):
        """计算单价"""
        if self.spec:
            return float(self.food.price) + float(self.spec.extra_price)
        return float(self.food.price)
    
    @property
    def total_price(self):
        """计算总价"""
        return self.price * self.count


class Order(models.Model):
    """
    订单模型
    """
    ORDER_STATUS = (
        (1, '待确认'),
        (2, '制作中'),
        (3, '已完成'),
        (4, '已取消'),
    )
    
    PAYMENT_METHOD = (
        ('online', '在线支付'),
        ('offline', '线下支付'),
    )
    
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='orders', verbose_name="用户")
    order_number = models.CharField(max_length=100, unique=True, verbose_name="订单号")
    total_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="总价")
    status = models.IntegerField(choices=ORDER_STATUS, default=1, verbose_name="状态")
    payment_method = models.CharField(max_length=20, choices=PAYMENT_METHOD, default='online', verbose_name="支付方式")
    table_number = models.CharField(max_length=50, null=True, blank=True, verbose_name="桌号/取餐号")
    address = models.ForeignKey('Address', on_delete=models.SET_NULL, null=True, blank=True, verbose_name="收货地址")
    address_text = models.TextField(null=True, blank=True, verbose_name="收货地址文本")
    remark = models.TextField(null=True, blank=True, verbose_name="备注")
    shipping_fee = models.DecimalField(max_digits=10, decimal_places=2, default=0, verbose_name="配送费")
    
    # 时间字段
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    paid_at = models.DateTimeField(null=True, blank=True, verbose_name="付款时间")
    delivered_at = models.DateTimeField(null=True, blank=True, verbose_name="配送/制作时间")
    received_at = models.DateTimeField(null=True, blank=True, verbose_name="收货时间")
    finished_at = models.DateTimeField(null=True, blank=True, verbose_name="完成时间")
    canceled_at = models.DateTimeField(null=True, blank=True, verbose_name="取消时间")
    
    class Meta:
        verbose_name = "订单"
        verbose_name_plural = verbose_name
        ordering = ['-created_at']
    
    def __str__(self):
        return self.order_number
    
    def save(self, *args, **kwargs):
        # 记录状态变更
        is_new = self.pk is None
        
        if not is_new:
            # 获取数据库中当前对象的状态
            old_obj = Order.objects.get(pk=self.pk)
            old_status = old_obj.status
            
            # 如果订单状态从其他状态变为已完成，更新相关食品的销量
            if old_status != 3 and self.status == 3:
                self.update_food_sold_count()
                
                # 设置完成时间
                if not self.finished_at:
                    self.finished_at = timezone.now()
            
            # 如果订单状态从待付款变为已付款，设置支付时间
            if old_status == 1 and self.status == 2:
                if not self.paid_at:
                    self.paid_at = timezone.now()
                    
            # 如果订单状态从已付款变为配送中，设置配送时间
            if old_status == 2 and self.status == 3:
                if not self.delivered_at:
                    self.delivered_at = timezone.now()
        
        super().save(*args, **kwargs)
    
    def update_food_sold_count(self):
        """更新订单中所有食品的销量"""
        from django.db import transaction
        import logging
        
        logger = logging.getLogger('api')
        
        try:
            with transaction.atomic():
                # 获取订单中的所有商品项
                order_items = self.items.all()
                
                for item in order_items:
                    # 增加食品销量
                    food = item.food
                    food.sold += item.count
                    food.save()
                    
                    logger.info(f"更新食品 {food.name}(ID:{food.id}) 销量 +{item.count}, 当前销量: {food.sold}")
                
                logger.info(f"订单 {self.order_number} 更新食品销量成功")
        except Exception as e:
            logger.error(f"更新食品销量失败: {str(e)}")
            # 不抛出异常，确保订单状态变更不受影响


class OrderItem(models.Model):
    """
    订单项模型
    """
    order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='items', verbose_name="订单")
    food = models.ForeignKey(Food, on_delete=models.CASCADE, verbose_name="食品")
    food_name = models.CharField(max_length=100, verbose_name="食品名称")
    food_image = models.URLField(max_length=500, verbose_name="食品图片")
    food_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name="食品价格")
    spec = models.CharField(max_length=100, null=True, blank=True, verbose_name="规格")
    count = models.IntegerField(verbose_name="数量")
    
    class Meta:
        verbose_name = "订单项"
        verbose_name_plural = verbose_name
    
    def __str__(self):
        return f"{self.order.order_number}-{self.food_name}"
    
    @property
    def total_price(self):
        """计算总价"""
        return float(self.food_price) * self.count


class Address(models.Model):
    """
    收货地址模型
    """
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='addresses', verbose_name="用户")
    name = models.CharField(max_length=100, verbose_name="收货人")
    phone = models.CharField(max_length=20, verbose_name="电话")
    province = models.CharField(max_length=100, verbose_name="省份")
    city = models.CharField(max_length=100, verbose_name="城市")
    district = models.CharField(max_length=100, verbose_name="区县")
    detail = models.TextField(verbose_name="详细地址")
    is_default = models.BooleanField(default=False, verbose_name="是否默认")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
    
    class Meta:
        verbose_name = "收货地址"
        verbose_name_plural = verbose_name
        ordering = ['-is_default', '-updated_at']
    
    def __str__(self):
        return f"{self.name}的地址"
    
    def save(self, *args, **kwargs):
        """保存时，如果设为默认地址，其他地址设为非默认"""
        if self.is_default:
            Address.objects.filter(user=self.user, is_default=True).update(is_default=False)
        super().save(*args, **kwargs)
